#ifndef TASKHELPER_H
#define TASKHELPER_H

#include <mutex>
#include <memory>
#include <atomic>
#include <functional>
#include <QObject>
#include <thread>

// Task helper : do some task in GUI thread
// but *do* remember to execute QCoreApplication::precessEvents() 
// while doing long tasks.
class GuiTaskManager : public QObject
{
    Q_OBJECT
public:
    GuiTaskManager(QObject *parent);
    ~GuiTaskManager();

public:
    std::shared_ptr<std::atomic<bool>> guiTask(std::function<void()> func);
    template <class T>
    T guiTaskWait(std::function<T()> func);
private:
    // internal listeners
    std::mutex helpTasksMutex;
    std::list<std::pair<std::shared_ptr<std::atomic<bool>>, std::function<void()>>> helpTasks;
    void on_taskHelperTimerTimeout();
    QTimer taskHelperTimer;
private:
    
};

template <>
inline void GuiTaskManager::guiTaskWait(std::function<void()> func)
{
    auto f = guiTask(func);

    while (f->load() != true)
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    return;
}

template <class T>
inline T GuiTaskManager::guiTaskWait(std::function<T()> func)
{
    T retv;
    auto f = guiTask([&]()
    {
        retv = std::move(func());
    });

    while (f->load() != true)
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    return retv;
}
#endif // TASKHELPER_H
